package com.henry.imgproc;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Arrays;

public class MedianFilter {
    public static BufferedImage medianFilter(BufferedImage inImage, int kernelX, int kernelY) throws Exception {
        if (kernelX < 3 || kernelX % 2 == 0 || kernelY < 3 || kernelY % 2 == 0) {
            throw new Exception("Invalid kernel size.");
        }

        if (kernelX > inImage.getWidth() || kernelY > inImage.getHeight()) {
            throw new Exception("Too big kernel for input image.");
        }

        int edgeX = kernelX / 2;
        int edgeY = kernelY / 2;

        BufferedImage result = new BufferedImage(inImage.getWidth(), inImage.getHeight(), inImage.getType());

        int[] B = new int[kernelX * kernelY];
        int[] G = new int[kernelX * kernelY];
        int[] R = new int[kernelX * kernelY];

        for (int y = 0; y <= inImage.getHeight() - kernelY; y++) { // rows
            for (int x = 0; x <= inImage.getWidth() - kernelX; x++) { // columns
                for (int m = 0; m < kernelY; m++) {
                    for (int n = 0; n < kernelX; n++) {
                        Color pixel = new Color(inImage.getRGB(x + n, y + m));
                        B[m * kernelX + n] = pixel.getBlue();
                        G[m * kernelX + n] = pixel.getGreen();
                        R[m * kernelX + n] = pixel.getRed();
                    }
                }
                Arrays.sort(B);
                Arrays.sort(G);
                Arrays.sort(R);
                Color newPixel = new Color(R[R.length / 2], G[G.length / 2], B[B.length / 2]);
                result.setRGB(x + edgeX, y + edgeY, newPixel.getRGB());
            }
        }

        // Processing Edges: Kind of annoying... Left unimplemented...

        return result;
    }
}
